// auto-register.util.ts
// 导入path模块的所有内容
import * as path from 'path';
// 导入fs模块的所有内容
import * as fs from 'fs';
// 从@nestjs/common导入DynamicModule, Global, Module
import { DynamicModule, Module, Type } from '@nestjs/common';

// 定义一个接口AutoRegisterOptions，包含一个path属性
export interface AutoRegisterOptions {
  path: string;
}

// 定义一个类, 并且@Module装饰器设置为module
@Module({})
export class AutoRegisterModule {
  // 静态方法registerModules，接收一个AutoRegisterOptions对象，返回一个DynamicModule对象
  static registerModules(options: AutoRegisterOptions): DynamicModule {
    // 调用loadModules方法获取模块数组
    const modules = this.loadModules(options.path);
    // 返回一个包含module和imports属性的对象
    return {
      module: AutoRegisterModule,
      imports: modules,
    };
  }

  // 私有静态方法loadModules，接收一个目录路径，返回模块数组
  private static loadModules(directory: string): Type<any>[] {
    // 将当前目录与传入目录拼接成完整路径
    const normalizedPath = path.join(__dirname, directory);
    // 调用loadModulesRecursively方法递归加载模块
    return this.loadModulesRecursively(normalizedPath);
  }

  // 私有静态方法loadModulesRecursively，递归加载模块
  private static loadModulesRecursively(directory: string): any[] {
    // 读取目录中的文件
    const files = fs.readdirSync(directory);

    // 使用reduce方法遍历文件，并累加模块数组
    return files.reduce((importedModules: Type<any>[], file) => {
      // 拼接文件的完整路径
      const filePath = path.join(directory, file);
      // 检查文件是否是目录
      const isDirectory = fs.statSync(filePath).isDirectory();
      if (isDirectory) {
        // 如果是目录，则递归加载子目录中的模块
        importedModules.push(...this.loadModulesRecursively(filePath));
      } else if (file.endsWith('.module.js')) {
        // 如果是以.module.js结尾的文件，则加载该文件
        // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports
        const module = require(filePath);
        // 如果模块存在且有一个默认导出，则将该默认导出添加到模块数组中
        if (module && module.default) {
          importedModules.push(module.default);
        } else {
          // 如果没有默认导出，则输出错误信息
          console.error(
            `Module at ${filePath} does not have a default export.`,
          );
        }
      }

      // 返回累加后的模块数组
      return importedModules;
    }, []);
  }
}

